package jp.co.mclnet.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import jp.co.mclnet.dao.JdbcDaoImpl;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class KobayashiCalc2 {

    // table name
    public static final String XYZ_SPEED = "xyz_speed";
    public static final String XYZ_DISPLAY = "xyz_display";

    public static void main(String[] args) {

        JdbcDaoImpl dao = null;
        // String filePath = "deprecated/xls/display.xls";
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException(e);
        }
        Connection conn = null;
        try {
            conn = DriverManager
                    .getConnection(
                            "jdbc:mysql://localhost:3306/saturday?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true",
                            "root", "");

            // xlsファイルの中身を取得
            // LinkedList<Object> list = toListXYZ(filePath);
            // テーブルの中身を取得する
            // dao = new JdbcDaoImpl(XYZ_SPEED);
            dao = new JdbcDaoImpl(XYZ_DISPLAY);
            dao.setConnection(conn);
            Iterator<HashMap<String, Object>> it = dao
                    .read(new HashMap<String, Object>());
            List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
            // 取得した中身をlistへ保存
            while (it.hasNext()) {
                list.add(it.next());
            }
            System.out.println(list);
            // table= 座標の取得
            List<HashMap<String, Object>> tableNameList = new ArrayList<HashMap<String, Object>>();
            tableNameList = getLikeXyz(list, "table=");
            System.out.println(tableNameList);
            // テーブル数ループ
            for (int i = 0; tableNameList.size() > i; i++) {
                // 基準値(table= がある y+1 した座標)
                Map<String, Object> protTableName = tableNameList.get(i);
                // int x = protTableName.get("x");
                // int y = protTableName.get("y") + 1;
                // int z = protTableName.get("z");
                // Object protOriginValue = getValue4Xyz(list, x, y, z);

                System.out.println(protTableName);
                // テーブルのしたの座標と項目がほしいよー
                // while(x軸のvalueが空になるまで){
                //     //テーブルの縦じくと項目がほしいよー
                //     while(y軸のvalueが空になるまで){
                //     }

                // }
            }
        } catch (SQLException e) {
            throw new IllegalArgumentException(e);
            // } catch (IOException e) {
            // throw new IllegalArgumentException(e);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    conn = null;
                } catch (SQLException e) {
                    throw new IllegalArgumentException(e);
                }
            }

        }
    }

    // TODO テーブルへの接続とメソッド/クラスの切り出しを考える
    // TODO speedタイプにも対応ができるようにすること
    // TODO 考え方としては、A-0かtabeleName列tabeleName行+1の違いだけ
    // TODO エクセルからの切り出し方は同じになるはず
    /**
     * likeっぽく値を取得するためのメソッド
     * @param list ファイルの中身をリスト化したもの
     * @param value 文字列
     * @return value値を含んだ 座標群
     */
    protected static List<HashMap<String, Object>> getLikeXyz(
            List<HashMap<String, Object>> list, String value) {

        List<HashMap<String, Object>> gridChart = new ArrayList<HashMap<String, Object>>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = (Map<String, Object>) list.get(i);
            String str = (String) map.get("value");
            if (str.contains(value)) {
                HashMap<String, Object> gridMap = new HashMap<String, Object>();
                gridMap.put("x", map.get("x"));
                gridMap.put("y", map.get("y"));
                gridMap.put("z", map.get("z"));
                gridMap.put("value", map.get("value"));
                gridChart.add(gridMap);
            }
        }
        if (gridChart.size() == 0) {
            return null;
        }
        return gridChart;
    }

    /**
     * ピンポイントで値を返すメソッド
     * @param list ファイルの中身をリスト化したもの
     * @param x 座標
     * @param y 座標
     * @param z 座標
     * @return value
     */
    protected static Object getValue4Xyz(List<HashMap<String, Object>> list,
            int x, int y, int z) {

        // 引数Xと同じ座標Xに存在するY,Z,valueを取得する
        List<LinkedHashMap<String, Object>> gridX = new ArrayList<LinkedHashMap<String, Object>>();
        LinkedHashMap<String, Object> gridMapX = new LinkedHashMap<String, Object>();
        for (int i = 0; i < list.size(); i++) {
            LinkedHashMap map = (LinkedHashMap) list.get(i);
            int valueX = (int) map.get("x");
            if (valueX == x) {
                gridMapX.put("y", (int) map.get("y"));
                gridMapX.put("z", (int) map.get("z"));
                gridMapX.put("value", (int) map.get("value"));
                gridX.add(gridMapX);
            }
        }
        // 引数Yと同じ座標Xに存在するZ,valueを取得する
        List<LinkedHashMap<String, Object>> gridY = new ArrayList<LinkedHashMap<String, Object>>();
        LinkedHashMap<String, Object> gridMapY = new LinkedHashMap<String, Object>();
        for (int i = 0; i < gridX.size(); i++) {
            LinkedHashMap map = (LinkedHashMap) gridX.get(i);
            int valueY = (int) map.get("y");
            if (valueY == y) {
                gridMapY.put("z", (int) map.get("z"));
                gridMapY.put("value", (int) map.get("value"));
                gridY.add(gridMapY);
            }
        }
        // 引数Zと同じ座標Zに存在するvalueを取得する
        for (int i = 0; i < gridY.size(); i++) {
            LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) gridY
                    .get(i);
            int valueZ = (int) map.get("z");
            if (valueZ == z) {
                return map.get("value");
            }
        }
        return null;
    }

    /**
     * 値から座標を取得するメソッド
     * @param list ファイルの中身をリスト化したもの
     * @param value 文字列
     * @return 座標
     */
    protected static List<LinkedHashMap<String, Object>> getXyz4Value(
            List list, String value) {
        List<LinkedHashMap<String, Object>> gridChart = new ArrayList<LinkedHashMap<String, Object>>();
        for (int i = 0; i < list.size(); i++) {
            LinkedHashMap map = (LinkedHashMap) list.get(i);
            String str = (String) map.get("value");
            if (value.equals(str)) {
                LinkedHashMap<String, Object> gridMap = new LinkedHashMap<String, Object>();
                gridMap.put("x", map.get("x"));
                gridMap.put("y", map.get("y"));
                gridMap.put("z", map.get("z"));
                gridChart.add(gridMap);
            }
        }
        if (gridChart.size() == 0) {
            return null;
        }
        return gridChart;
    }

    /**
     * @param filePath xlsファイル
     * @return xlsファイルの中身をリスト化したもの
     * @throws IOException
     */
    protected static LinkedList<Object> toListXYZ(String filePath)
            throws IOException {
        LinkedList<Object> list = new LinkedList<Object>();
        InputStream is = null;
        try {
            is = new FileInputStream(filePath);

            is = new BufferedInputStream(is);
            POIFSFileSystem pfs = new POIFSFileSystem(is);
            HSSFWorkbook book = new HSSFWorkbook(pfs);
            // -- Z 軸
            for (int z = 0; z < book.getNumberOfSheets(); z++) {
                HSSFSheet sheet = book.getSheetAt(z);
                int firstRowNum = sheet.getFirstRowNum();
                int lastRowNum = sheet.getLastRowNum();
                // -- Y 軸
                for (int y = firstRowNum; y <= lastRowNum; y++) {
                    HSSFRow row = (HSSFRow) sheet.getRow(y);
                    if (row == null) {
                        continue;
                    }
                    short firstCellNum = row.getFirstCellNum();
                    short lastCellNum = row.getLastCellNum();
                    // -- X 軸
                    for (short x = firstCellNum; x <= lastCellNum; x++) {
                        HSSFCell cell = (HSSFCell) row.getCell((int) x);
                        if (cell == null) {
                            continue;
                        }

                        Map v = new LinkedHashMap();
                        v.put("x", (int) x);
                        v.put("y", y);
                        v.put("z", z);
                        v.put("value", CalcUtils.getValue(cell));
                        System.out.println(v);
                        list.add(v);
                    }
                }
            }
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException(e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
        return list;
    }

}
